﻿/*
 * Copyright © 2020, Wuxi Safover Intelligent Technology Co., Ltd. All rights reserved.
 * 
 * 无锡安永智能科技有限公司版权所有，未经许可，不得用于商业用途
 * 
 * Visit: https://www.safover.com/ 
 */

using Safover.LidarCollector.Extensions;
using Safover.LidarCollector.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Safover.LidarCollector.Config
{
    public class RuntimeConfigManager
    {

        public static RuntimeConfigManager Instance { get; } = new RuntimeConfigManager();

        public static string RootPath => AppConfig.RootPath;

        public static string FullRootPath => Path.GetFullPath(RootPath);

        public OpticalMaserConfig OpticalMaserConfig { get; private set; }

        public PowerBoardConfig PowerBoardConfig { get; private set; }

        public AcquisitionCardConfig AcquisitionCardConfig { get; private set; }

        public RotaryTableConfig RotaryTableConfig { get; private set; }

        public ElectronicCompassConfig ElectronicCompassConfig { get; private set; }

        public GPSConfig GPSConfig { get; private set; }

        public LidarConfig LidarConfig { get; private set; }

        public OthersConfig OthersConfig { get; private set; }

        public DeviceConfig DeviceConfig { get; private set; }

        private RuntimeConfigManager()
        {
            LoadConfigs();
        }

        public void LoadConfigs()
        {
            DeviceConfig = LoadDeviceConfig();

            OpticalMaserConfig = LoadOpticalMaserConfig();
            PowerBoardConfig = LoadPowerBoardConfig();
            AcquisitionCardConfig = LoadAcquisitionCardConfig();
            RotaryTableConfig = LoadRotaryTableConfig();
            ElectronicCompassConfig = LoadElectronicCompassConfig();
            GPSConfig = LoadGPSConfig();

            OthersConfig = LoadOthersConfig();

            LidarConfig = LoadLidarConfig();
        }

        private DeviceConfig LoadDeviceConfig()
        {
            return BaseConfig<DeviceConfig>.FromJson(Path.Combine(RootPath, DeviceConfig.JsonFileName));
        }

        private OthersConfig LoadOthersConfig()
        {
            return BaseConfig<OthersConfig>.FromJson(Path.Combine(RootPath, OthersConfig.JsonFileName));
        }

        public void Save(OthersConfig config)
        {
            BaseConfig<OthersConfig>.SaveJson(config, Path.Combine(RootPath, OthersConfig.JsonFileName));
            OthersConfig = LoadOthersConfig();
        }

        private LidarConfig LoadLidarConfig()
        {
            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto,
                SerializationBinder = new KnownTypesBinder
                {
                    KnownTypes = new List<Type>
                    {
                        typeof(VerticalScanConfig),
                        typeof(HorizontalScanConfig),
                        typeof(FixedDirectionScanConfig),
                    }
                }
            };

            return BaseConfig<LidarConfig>.FromJson(Path.Combine(RootPath, LidarConfig.JsonFileName), settings);
        }

        public void Save(LidarConfig config)
        {
            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto,
                SerializationBinder = new KnownTypesBinder
                {
                    KnownTypes = new List<Type>
                    {
                        typeof(VerticalScanConfig),
                        typeof(HorizontalScanConfig),
                        typeof(FixedDirectionScanConfig),
                        typeof(VerticalBlindSectorConfig),
                        typeof(HorizontalBlindSectorConfig),
                    }
                }
            };

            BaseConfig<LidarConfig>.SaveJson(config, Path.Combine(RootPath, LidarConfig.JsonFileName), settings);
            LidarConfig = LoadLidarConfig();
        }

        private OpticalMaserConfig LoadOpticalMaserConfig()
        {
            return BaseConfig<OpticalMaserConfig>.FromJson(Path.Combine(RootPath, OpticalMaserConfig.JsonFileName));
        }

        public void Save(OpticalMaserConfig config)
        {
            BaseConfig<OpticalMaserConfig>.SaveJson(config, Path.Combine(RootPath, OpticalMaserConfig.JsonFileName));
            OpticalMaserConfig = LoadOpticalMaserConfig();
        }

        private PowerBoardConfig LoadPowerBoardConfig()
        {
            return BaseConfig<PowerBoardConfig>.FromJson(Path.Combine(RootPath, PowerBoardConfig.JsonFileName));
        }

        public void Save(PowerBoardConfig config)
        {
            BaseConfig<PowerBoardConfig>.SaveJson(config, Path.Combine(RootPath, PowerBoardConfig.JsonFileName));
            PowerBoardConfig = LoadPowerBoardConfig();
        }

        private AcquisitionCardConfig LoadAcquisitionCardConfig()
        {
            return BaseConfig<AcquisitionCardConfig>.FromJson(Path.Combine(RootPath, AcquisitionCardConfig.JsonFileName));
        }

        public void Save(AcquisitionCardConfig config)
        {
            BaseConfig<AcquisitionCardConfig>.SaveJson(config, Path.Combine(RootPath, AcquisitionCardConfig.JsonFileName));
            AcquisitionCardConfig = LoadAcquisitionCardConfig();
        }

        private RotaryTableConfig LoadRotaryTableConfig()
        {
            return BaseConfig<RotaryTableConfig>.FromJson(Path.Combine(RootPath, RotaryTableConfig.JsonFileName));
        }

        public void Save(RotaryTableConfig config)
        {
            BaseConfig<RotaryTableConfig>.SaveJson(config, Path.Combine(RootPath, RotaryTableConfig.JsonFileName));

            RotaryTableConfig = LoadRotaryTableConfig();
        }

        private ElectronicCompassConfig LoadElectronicCompassConfig()
        {
            return BaseConfig<ElectronicCompassConfig>.FromJson(Path.Combine(RootPath, ElectronicCompassConfig.JsonFileName));
        }
        public void Save(ElectronicCompassConfig config)
        {
            BaseConfig<ElectronicCompassConfig>.SaveJson(config, Path.Combine(RootPath, ElectronicCompassConfig.JsonFileName));
            ElectronicCompassConfig = LoadElectronicCompassConfig();
        }

        private GPSConfig LoadGPSConfig()
        {
            return BaseConfig<GPSConfig>.FromJson(Path.Combine(RootPath, GPSConfig.JsonFileName));
        }
        public void Save(GPSConfig config)
        {
            BaseConfig<GPSConfig>.SaveJson(config, Path.Combine(RootPath, GPSConfig.JsonFileName));
            GPSConfig = LoadGPSConfig();
        }
    }

    internal class KnownTypesBinder : ISerializationBinder
    {
        public IList<Type> KnownTypes { get; set; }

        public Type BindToType(string assemblyName, string typeName)
        {
            return KnownTypes.SingleOrDefault(t => t.Name == typeName);
        }

        public void BindToName(Type serializedType, out string assemblyName, out string typeName)
        {
            assemblyName = null;
            typeName = serializedType.Name;
        }
    }
}
